// Iter_Alg.cpp : Defines the entry point for the console application.
//
//���������. ����������� ���������. ���������.

#include "stdafx.h"
#include "Header.h"

#define	  stop __asm nop

int _tmain(int argc, _TCHAR* argv[])
{
	
///////////////////////////////////////////////////////////////////

	//������� 1. ���������

	//����������� ���������. ����������� set<Point>. ���������, ���
	//����� ����������� � ������ Point. �������� ������, �������� �������� 
	//�������� ������� ��������� set, �� ����������� �� ��������
	
	set<Point> s_p{Point(1,1),Point(10,10), Point(3,3), Point(6,6), Point()};
	vector<Point> v;
	copy(s_p.crbegin(), s_p.crend(), back_inserter(v));
	

	//��������� ���������. � ������� ostream_iterator �������� ����������
	//vector � set �� ����������� ������� �� �����.
	ostream_iterator<Point> it(cout, " ");
	cout <<"Set:" << endl;
	copy(s_p.cbegin(), s_p.cend(), it);
	
	cout << endl << "Vector:" << endl;
	copy(v.cbegin(), v.cend(), it);
	cout << endl;

	_asm nop
	//��������� �������. � ������� ������������ ���������:
	//back_inserter()
	//front_inserter()
	//inserter()
	//���������� ������� �������� �������� � ����� �� ��������� �����������. ���������:
	//����� �� ���������� ������� ����� ������������ � ������ �����������.
	
	Point arr[]{ Point(1,3),Point(6,10), Point(3,9), Point(8,6), Point(15,15) };
	//copy(arr, arr+2, back_inserter(s_p)); // push_back �� ����������� � set
	//copy(arr + 2, arr + 4, front_inserter(s_p));push_front �� ����������� � set
	copy(arr + 4, arr + 5, inserter(s_p,find_if(s_p.cbegin(), s_p.cend(),PRED(*(arr+4)))));
	
	cout << "Set after pasting:" << endl;
	copy(s_p.cbegin(), s_p.cend(), it);

	
	copy(arr, arr+3, back_inserter(v));
	//copy(arr, arr + 5, front_inserter(v)); push_front �� ����������� � vector
	copy(arr+3, arr + 5, inserter(v,v.begin()));
	
	cout << endl << "Vector after pasting:" << endl;
	copy(v.cbegin(), v.cend(), it);
	cout << endl;
	_asm nop
///////////////////////////////////////////////////////////////////

	//������� 2. ���������� ��������� (������������ ���� <algorithm>). ���������.

	// �������� for_each() - ����� �������� ������� ��� ������� �������� ����� ������������������
	//(������, vector, list...)
	//� ������� ��������� for_each � ����� ������������������ � ���������� ������ ����
	//������������ �������� ���������
	//��������� : ������� ���������� ������� ���������� ��� ������
	list<string> list_string{"Hi","Why", "Bye", "May", "Lay", "Stay", "Away"};
	int arr_int[]{10,12,15,45,16};
	
	cout << "Set<Point> for_each:" << endl;
	set<Point>::const_iterator it_2 = s_p.begin();
	std::advance(it_2, 3);
	for_each(s_p.cbegin(), it_2, print_elem<Point>);
	
	cout << endl << "Vector<Point> for_each:" << endl;
	vector<Point>::const_iterator it_3 = v.begin();
	std::advance(it_3, 4);
	for_each(v.cbegin(), it_3, print_elem<Point>);
	
	cout << endl << "List<string> for_each:" << endl;
	for_each(list_string.cbegin(), list_string.cend(), print_elem<string>);
	
	cout << endl << "Array<int> for_each:" << endl;
	for_each(arr_int, arr_int + (sizeof(arr_int) / sizeof(arr_int[0])), print_elem<int>);
	cout << endl;
	stop

	//� ������� ��������� for_each � ����� ������������������ � ���������� ���� Point
	//�������� "����������" �� ��������� �������� (����� �������� ���� ����� ����������� 
	//��� ������) � �������� ��������� � ������� ����������� ���������(����� ��� ������???)
	
	list<Point> l_p{ v.cbegin(),it_3 };
	deque<Point> deq_p{ v.cbegin(),it_3 };
	
	
	cout << endl << "Vector:" << endl;
	vector<Point> vec_p;
	vec_p.reserve(4);
	copy(v.cbegin(), it_3, back_inserter(vec_p));
	copy(vec_p.cbegin(), vec_p.cend(), it);
	cout << endl;
		
	for_each(vec_p.begin(), vec_p.end(),Set_point<Point>(Point(3,3))); //
	copy(vec_p.cbegin(), vec_p.cend(), it);
	cout << endl;

	cout << endl << "List:" << endl;
	copy(l_p.cbegin(), l_p.cend(), it);
	cout << endl;
	for_each(l_p.begin(), l_p.end(), Set_point<Point>(Point(3, 3)));
	copy(l_p.cbegin(), l_p.cend(), it);
	cout << endl;

	cout << endl << "Deque:" << endl;
	copy(deq_p.cbegin(), deq_p.cend(), it);
	cout << endl;
	for_each(deq_p.begin(), deq_p.end(), Set_point<Point>(Point(3, 3)));
	copy(deq_p.cbegin(), deq_p.cend(), it);
	cout << endl;
		

	stop
	//� ������� ��������� find() ������� � ����� ������������������ ��������� Point
	//��� ��������� �� ������� Point � ��������� ���������.
	cout << endl << "Find iterators of Point x:" << endl;
	deq_p.push_back(Point(13,13));
	deq_p.push_front(Point(13, 13));
	copy(deq_p.cbegin(), deq_p.cend(), it);
	
	list <deque<Point>::iterator> res;
	deque<Point>::iterator deq_p_it_b = deq_p.begin(), deq_p_it_e = deq_p.end();
	while (deq_p_it_b != deq_p_it_e)
	{
		deq_p_it_b = find_if(deq_p_it_b, deq_p_it_e, Find_point(Point(13, 13)));
		if (deq_p_it_b == deq_p_it_e)break;
		res.push_back(deq_p_it_b);
		++deq_p_it_b;
	}

	stop
	//� ������� ��������� sort() ������������ ����� ������������������ ��������� Point. 
	////�� ��������� �������� ��������� ������������������ �� �����������.
	//��� ������ ���� ���������� � ������ Point?
	// ���������: ���������� �������� sort �� �������� �� �������, ��� ���
	//��� ���� �� �� ���������� => ��� ������ ���������� ����������� ������� ������!!!
	
	sort(deq_p.begin(), deq_p.end());

	cout << endl << "Sort deque<Point>:" << endl;
	copy(deq_p.cbegin(), deq_p.cend(), it);

	stop

	
	//� ������� ��������� find_if() ������� � ����� ������������������ ��������� Point
	//�������� �� ������� Point, ��������������� �������: ���������� x � y ����� � ����������
	//[-n, +m].
	deq_p.push_back(Point(-3,4));
	double n = -4, m =0.4;
	deque<Point>::const_iterator d_it = find_if(deq_p.cbegin(), deq_p.cend(), Find_point_if(n, m));
	cout << endl << "Result of find_if when \"x \" of \"Point\" between (-4, 0.4):" << endl << * d_it << endl;
	
	//� ������� ��������� sort() ������������ ����� ������������������ ��������� Rect,
	//���������� �������������� �� �������� ������ �� ������ ���������.
	
	deque<Rect> d_rect{Rect(1,5,4,7),Rect(5,7,4,1), Rect(7,8,6,4), Rect(47,1,5,3), Rect(0,1,5,4)};
	list<Point> l_centres;
	ostream_iterator<Rect> it_R(cout, " ");

	/*transform(d_rect.cbegin(), d_rect.cend(), back_inserter(l_centres), Center);
	cout << endl << "deque<Rect>:" << endl;
	copy(d_rect.begin(), d_rect.end(), it_R);
	cout << endl << "Centers:" << endl;
	copy(l_centres.cbegin(), l_centres.cend(), it);*/
	
	
	sort(d_rect.begin(), d_rect.end(), Sort_distance_from);
	/*transform(d_rect.cbegin(), d_rect.cend(), l_centres.begin(), Center);
	cout << endl << "Sort deque<Rect>:" << endl;
	copy(d_rect.cbegin(), d_rect.cend(), it_R);
	cout << endl << "Centers:" << endl;
	copy(l_centres.cbegin(), l_centres.cend(), it);*/

	stop
	{//transform
		//�������� �������, ������� � ������� ��������� transform ��������� 
		//���������� ������� string � ������ �������.
		//���������: ����� string - ��� "�����" ���������, ������� ��� ����
		// ���������� ������ begin() � end()

		string s {"DDrtRf"};
		transform(s.begin(), s.end(), s.begin(), tolower);
		
		//��������� list ��������� string. � ������� ��������� transform ����������
		//�������� "�������" set, ����������� ������ � ������ �������
	
		list<string> l_str{"Hi","May","Bye"};
		set<string> set_str;
		auto lambda = [](const string& str) {string N_str = str; for (auto& x : N_str) { x=tolower(x); } return N_str; };
		transform(l_str.begin(), l_str.end(),inserter(set_str, set_str.begin()), lambda);
		ostream_iterator<string> it_str(cout, " ");
		copy(set_str.cbegin(), set_str.cend(), it_str);

		stop
	}
	
	{//copy_if
		//��� ������ � ���������� ���� string. � ������� copy_if() ���������
		//������� ������� ������, ������������ � ����� "�" ��� "�", ����� � "�"...
		//��� ���� ������� ����� � �������� ������� ������ �� �����!
		vector<string>v_str{ "Bank","avalon","Soda", "Rom", "Bloom", "Bad", "Argentina", "Coffe" };
		ostream_iterator<string> it_str(cout, " ");
		cout << endl;
		for (char i = 'A'; i <= 'Z'; i++)
		{
			int count = 0;
			Vector_leks V_l(i, count);
			
			copy_if(v_str.cbegin(), v_str.cend(), it_str, V_l);
			if (count) { cout << endl; }
		}
		
		/*for (char i = 'A'; i <= 'Z'; i++)
		{
			int count = 0;
			auto V_l=[&count,i](const auto& str) {if (toupper(str[0]) == toupper(i)) { count++; return true; } else return false; };

			copy_if(v_str.cbegin(), v_str.cend(), it_str, V_l);
			if (count) { cout << endl; }
		}
		stop*/

		//��� multimap, ���������� ����: "����� - ���������� ���� � ������"
		//pair<string, int>. � ������� copy_if ����������� ��� map-�: ������ -
		//� ������, ����������� ������ ���������� ����, 2-�� - ��������.
		std::multimap<string, int> month {
			{"January", 31}, {"February", 28}, {"February", 29}, { "March", 31},
			{"April", 30}, {"May",31}, {"June", 30}, {"July", 31}, {"August",31},
			{"September",30}, {"October", 31}, {"November",30}, {"December",31}
		};

		map<string, int> even_months;
		map<string, int> odd_months;


		copy_if(month.cbegin(), month.cend(), inserter(odd_months, odd_months.begin()), how_many_days);
		set_difference(month.cbegin(), month.cend(), odd_months.cbegin(), odd_months.cend(), inserter(even_months, even_months.begin()));

		//copy_if(month.cbegin(), month.cend(), inserter(odd_months, odd_months.begin()), [](const pair<const string, int>& month) {return month.second & 1 ? false : true; } );
		
		stop

		//������������ multimap � map-�, ��������� ���������� ���� ����� ������
		//�������, ��������� �������� ������ ���������� �� ������.
		//��� ����� ������� ������������� ��� ������ ����?
		cout << endl <<"month"<<endl;
		print_container(month);
		cout << endl << "even_months" << endl;
		print_container(even_months);
		cout << endl << "odd_months" << endl;
		print_container(odd_months);
	
		stop
	}

	return 0;
}

